﻿using EnvDTE;
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using EnvDTE80;

namespace Sasa.QualityTools.CodeAnalysis.FxCopIntegrator.VisualStudio
{
    public class Solution
    {
        private EnvDTE.Solution solution;


        public string Path
        {
            get { return solution.FullName; }
        }

        public bool HasFxCopProjectFile
        {
            get
            {
                var fxcopProjectPath = PackageUtilities.GetFxCopProjectPath(solution);
                return File.Exists(fxcopProjectPath);
            }
        }

        public string FxCopProjectPath
        {
            get { return PackageUtilities.GetFxCopProjectPath(solution); }
        }

        public string CodeAnalysisDirectoryPath
        {
            get { return System.IO.Path.Combine(System.IO.Path.GetDirectoryName(solution.FullName), "CodeAnalysis"); }
        }

        public string ConfigurationPath
        {
            get { return System.IO.Path.Combine(CodeAnalysisDirectoryPath, "CodeAnalysisConfiguration.xml"); }
        }

        public string FxCopDictionaryPath
        {
            get { return System.IO.Path.Combine(CodeAnalysisDirectoryPath, "FxCopDictionary.xml"); }
        }

        public Project SelectedProject
        {
            get { return Project.CreateInstance(solution.DTE.SelectedItems.Item(1).Project); }
        }


        public Solution(EnvDTE.Solution solution)
        {
            this.solution = solution;
        }


        public bool Build()
        {
            solution.SolutionBuild.Build(true);
            return solution.SolutionBuild.LastBuildInfo == 0;
        }

        public void Open(string path, int? line)
        {
            var item = solution.FindProjectItem(path);
            if (item == null) return;

            if (item.IsOpen)
            {
                item.Document.Activate();
            }
            else
            {
                var window = item.Open(EnvDTE.Constants.vsViewKindCode);
                window.Visible = true;
                window.Activate();
            }

            // TODO get line
            if (line.HasValue)
            {
                ((TextSelection)item.Document.Selection).GotoLine(line.Value);
            }
        }

        public Project AddSolutionFolder(string name)
        {
            foreach (EnvDTE.Project project in solution.Projects)
            {
                if (project.Name == name && project.Kind == ProjectKinds.vsProjectKindSolutionFolder)
                {
                    return Project.CreateInstance(project);
                }
            }

            return Project.CreateInstance(((Solution2)solution).AddSolutionFolder(name));
        }

        public Project FindProjectByUniqueName(string uniqueName)
        {
            for (int i = 1; i <= solution.Count; i++)
            {
                var project = FindProjectByUniqueName(solution.Item(i), uniqueName);
                if (project != null)
                {
                    return project;
                }
            }
            return null;
        }

        private Project FindProjectByUniqueName(EnvDTE.Project project, string uniqueName)
        {
            if (project.Kind == ProjectKinds.vsProjectKindSolutionFolder)
            {
                return FindProjectByUniqueNameFromSolutionFolder(project, uniqueName);
            }
            else if (project.UniqueName == uniqueName)
            {
                return Project.CreateInstance(project);
            }
            else
            {
                return null;
            }
        }

        private Project FindProjectByUniqueNameFromSolutionFolder(EnvDTE.Project solutionFolder, string uniqueName)
        {
            for (int i = 1; i <= solutionFolder.ProjectItems.Count; i++)
            {
                var project = solutionFolder.ProjectItems.Item(i).Object as EnvDTE.Project;
                if (project != null)
                {
                    var result = FindProjectByUniqueName(project, uniqueName);
                    if (result != null)
                    {
                        return result;
                    }
                }
            }
            return null;
        }

        public Project FindProjectByAssemblyPath(string path)
        {
            foreach (var p in PackageUtilities.GetBuildTargetProjects(solution))
            {
                var project = Project.CreateInstance(p);
                if (path == project.AssemblyPath)
                {
                    return project;
                }
            }
            return null;
        }

        public IEnumerable<Project> GetBuildTargetProjects(bool onlyShouldBuildProject)
        {
            foreach (var project in PackageUtilities.GetBuildTargetProjects(solution, onlyShouldBuildProject))
            {
                yield return Project.CreateInstance(project);
            }
        }
    }
}
